mod ftp_client;
mod commands;
mod ui;
mod config;

use anyhow::Result;
use clap::Parser;
use tracing::{info, error};
use tracing_subscriber;

use crate::ftp_client::{FtpClient, ChecksumType, TransferPriority};
use crate::ui::progress::TransferStatus;

#[derive(Parser)]
#[command(name = "ftp-client")]
#[command(about = "A high-performance FTP client with encryption plugin support")]
struct Args {
    /// Server host
    #[arg(long, default_value = "localhost")]
    host: String,
    
    /// Server port
    #[arg(long, default_value = "21")]
    port: u16,
    
    /// Username
    #[arg(long)]
    username: Option<String>,
    
    /// Password
    #[arg(long)]
    password: Option<String>,
    
    /// Enable debug logging
    #[arg(long)]
    debug: bool,
    
    /// Interactive mode
    #[arg(long)]
    interactive: bool,
    
    /// Upload file
    #[arg(long)]
    upload: Option<String>,
    
    /// Download file
    #[arg(long)]
    download: Option<String>,
    
    /// Local file path for upload/download
    #[arg(long)]
    local_path: Option<String>,
    
    /// Disable resume functionality
    #[arg(long)]
    no_resume: bool,
    
    /// Enable checksum verification (md5 or sha256)
    #[arg(long)]
    checksum: Option<String>,
    
    /// Enable concurrent transfers
    #[arg(long)]
    concurrent: bool,
    
    /// Maximum concurrent transfers
    #[arg(long, default_value = "3")]
    max_concurrent: usize,
    
    /// Upload multiple files (comma-separated)
    #[arg(long)]
    upload_multiple: Option<String>,
    
    /// Download multiple files (comma-separated)
    #[arg(long)]
    download_multiple: Option<String>,
    
    /// Transfer priority (low, normal, high, critical)
    #[arg(long, default_value = "normal")]
    priority: String,
    
    /// Show queue statistics
    #[arg(long)]
    show_queue: bool,
}

#[tokio::main]
async fn main() -> Result<()> {
    let args = Args::parse();
    
    // 初始化日志
    init_logging(args.debug)?;
    
    info!("Starting FTP Client...");
    
    // 创建客户端
    let mut client = FtpClient::new();
    
    // 如果启用并发传输，初始化并发管理器
    if args.concurrent {
        client.init_concurrent_transfers(args.max_concurrent);
        info!("Concurrent transfers enabled with max {} concurrent transfers", args.max_concurrent);
    }
    
    // 连接到服务器
    match client.connect(&args.host, args.port).await {
        Ok(_) => info!("Connected to {}:{}", args.host, args.port),
        Err(e) => {
            error!("Failed to connect: {}", e);
            return Err(e);
        }
    }
    
    // 如果提供了用户名和密码，自动登录
    let username = args.username.clone();
    let password = args.password.clone();
    
    if let (Some(username), Some(password)) = (username, password) {
        match client.login(&username, &password).await {
            Ok(_) => info!("Logged in as {}", username),
            Err(e) => {
                error!("Login failed: {}", e);
                return Err(e);
            }
        }
    }
    
    // 解析校验和类型
    let checksum_type = if let Some(ref checksum_str) = args.checksum {
        match checksum_str.to_lowercase().as_str() {
            "md5" => Some(ChecksumType::Md5),
            "sha256" => Some(ChecksumType::Sha256),
            _ => {
                error!("Invalid checksum type: {}. Supported types: md5, sha256", checksum_str);
                return Err(anyhow::anyhow!("Invalid checksum type"));
            }
        }
    } else {
        None
    };
    
    // 解析优先级
    let priority = match args.priority.to_lowercase().as_str() {
        "low" => TransferPriority::Low,
        "normal" => TransferPriority::Normal,
        "high" => TransferPriority::High,
        "critical" => TransferPriority::Critical,
        _ => {
            error!("Invalid priority: {}. Supported priorities: low, normal, high, critical", args.priority);
            return Err(anyhow::anyhow!("Invalid priority"));
        }
    };
    
    // 运行交互模式或简单测试
    if args.interactive {
        run_interactive_mode(&mut client).await?;
    } else if args.concurrent {
        run_concurrent_transfers(&mut client, &args, !args.no_resume, checksum_type, priority).await?;
    } else if args.show_queue {
        show_queue_statistics(&mut client).await?;
    } else if let Some(upload_file) = args.upload {
        run_file_upload(&mut client, &upload_file, &args.local_path, !args.no_resume, checksum_type).await?;
    } else if let Some(download_file) = args.download {
        run_file_download(&mut client, &download_file, &args.local_path, !args.no_resume, checksum_type).await?;
    } else {
        run_simple_test(&mut client).await?;
    }
    
    // 断开连接
    client.quit().await?;
    
    Ok(())
}

fn init_logging(debug: bool) -> Result<()> {
    let level = if debug { "debug" } else { "info" };
    
    tracing_subscriber::fmt()
        .with_env_filter(tracing_subscriber::EnvFilter::new(level))
        .with_target(false)
        .with_thread_ids(true)
        .with_thread_names(true)
        .init();
    
    Ok(())
}

async fn run_interactive_mode(client: &mut FtpClient) -> Result<()> {
    info!("Starting interactive mode...");
    
    // 简单的交互循环
    loop {
        println!("\nFTP Client Commands:");
        println!("  pwd  - Print working directory");
        println!("  ls   - List directory contents");
        println!("  cd   - Change directory");
        println!("  pasv - Set passive mode");
        println!("  type - Set transfer type");
        println!("  quit - Exit");
        
        print!("ftp> ");
        use std::io::{self, Write};
        io::stdout().flush()?;
        
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        let input = input.trim();
        
        if input.is_empty() {
            continue;
        }
        
        let parts: Vec<&str> = input.split_whitespace().collect();
        let command = parts[0].to_lowercase();
        
        match command.as_str() {
            "pwd" => {
                match client.pwd().await {
                    Ok(path) => println!("Current directory: {}", path),
                    Err(e) => println!("Error: {}", e),
                }
            }
            "ls" => {
                let path = parts.get(1).map(|s| *s);
                match client.list(path).await {
                    Ok(entries) => {
                        for entry in entries {
                            println!("{}", entry);
                        }
                    }
                    Err(e) => println!("Error: {}", e),
                }
            }
            "cd" => {
                if let Some(path) = parts.get(1) {
                    match client.cwd(path).await {
                        Ok(_) => println!("Changed to directory: {}", path),
                        Err(e) => println!("Error: {}", e),
                    }
                } else {
                    println!("Usage: cd <path>");
                }
            }
            "pasv" => {
                match client.set_transfer_mode(shared::types::TransferMode::Passive).await {
                    Ok(_) => println!("Set to passive mode"),
                    Err(e) => println!("Error: {}", e),
                }
            }
            "type" => {
                if let Some(transfer_type) = parts.get(1) {
                    match client.set_transfer_type(transfer_type).await {
                        Ok(_) => println!("Set transfer type to: {}", transfer_type),
                        Err(e) => println!("Error: {}", e),
                    }
                } else {
                    println!("Usage: type <A|I>");
                }
            }
            "quit" | "exit" => {
                break;
            }
            _ => {
                println!("Unknown command: {}", command);
            }
        }
    }
    
    Ok(())
}

async fn run_simple_test(client: &mut FtpClient) -> Result<()> {
    info!("Running simple test...");
    
    // 测试基本命令
    println!("Testing FTP client functionality...");
    
    // 测试PWD
    match client.pwd().await {
        Ok(path) => println!("✅ Current directory: {}", path),
        Err(e) => println!("❌ PWD failed: {}", e),
    }
    
    // 测试PASV
    match client.set_transfer_mode(shared::types::TransferMode::Passive).await {
        Ok(_) => println!("✅ Passive mode set"),
        Err(e) => println!("❌ PASV failed: {}", e),
    }
    
    // 测试TYPE
    match client.set_transfer_type("A").await {
        Ok(_) => println!("✅ Transfer type set to ASCII"),
        Err(e) => println!("❌ TYPE failed: {}", e),
    }
    
    // 测试LIST
    match client.list(None).await {
        Ok(entries) => {
            println!("✅ Directory listing:");
            for entry in entries {
                println!("  {}", entry);
            }
        }
        Err(e) => println!("❌ LIST failed: {}", e),
    }
    
    println!("Simple test completed!");
    Ok(())
}

async fn run_file_upload(client: &mut FtpClient, remote_filename: &str, local_path: &Option<String>, enable_resume: bool, checksum_type: Option<ChecksumType>) -> Result<()> {
    let local_path = local_path.as_ref()
        .ok_or_else(|| anyhow::anyhow!("Local path required for upload"))?;
    
    let path = std::path::Path::new(local_path);
    if !path.exists() {
        return Err(anyhow::anyhow!("Local file does not exist: {}", local_path));
    }
    
    if enable_resume {
        println!("Uploading {} to {} (with resume support)...", local_path, remote_filename);
    } else {
        println!("Uploading {} to {} (no resume)...", local_path, remote_filename);
    }
    
    if let Some(ref checksum_type) = checksum_type {
        println!("  Checksum verification: {:?}", checksum_type);
    }
    
    match client.upload_file_with_resume_and_checksum(path, remote_filename, enable_resume, checksum_type).await {
        Ok(result) => {
            println!("✅ Upload completed!");
            println!("  Bytes transferred: {}", result.bytes_transferred);
            println!("  Duration: {:.2}s", result.duration.as_secs_f64());
            println!("  Speed: {:.2} KB/s", result.speed / 1024.0);
            if result.resumed {
                println!("  Resumed from offset: {} bytes", result.resume_offset);
            }
            if let Some(ref checksum) = result.checksum {
                println!("  Checksum: {} ({:?})", checksum.checksum, checksum.checksum_type);
            }
            if result.integrity_verified {
                println!("  Integrity verification: ✅ PASSED");
            } else {
                println!("  Integrity verification: ❌ FAILED");
            }
        }
        Err(e) => {
            println!("❌ Upload failed: {}", e);
            return Err(e);
        }
    }
    
    Ok(())
}

async fn run_file_download(client: &mut FtpClient, remote_filename: &str, local_path: &Option<String>, enable_resume: bool, checksum_type: Option<ChecksumType>) -> Result<()> {
    let local_path = local_path.as_ref()
        .ok_or_else(|| anyhow::anyhow!("Local path required for download"))?;
    
    let path = std::path::Path::new(local_path);
    
    if enable_resume {
        println!("Downloading {} to {} (with resume support)...", remote_filename, local_path);
    } else {
        println!("Downloading {} to {} (no resume)...", remote_filename, local_path);
    }
    
    if let Some(ref checksum_type) = checksum_type {
        println!("  Checksum verification: {:?}", checksum_type);
    }
    
    match client.download_file_with_resume_and_checksum(remote_filename, path, enable_resume, checksum_type).await {
        Ok(result) => {
            println!("✅ Download completed!");
            println!("  Bytes transferred: {}", result.bytes_transferred);
            println!("  Duration: {:.2}s", result.duration.as_secs_f64());
            println!("  Speed: {:.2} KB/s", result.speed / 1024.0);
            if result.resumed {
                println!("  Resumed from offset: {} bytes", result.resume_offset);
            }
            if let Some(ref checksum) = result.checksum {
                println!("  Checksum: {} ({:?})", checksum.checksum, checksum.checksum_type);
            }
            if result.integrity_verified {
                println!("  Integrity verification: ✅ PASSED");
            } else {
                println!("  Integrity verification: ❌ FAILED");
            }
        }
        Err(e) => {
            println!("❌ Download failed: {}", e);
            return Err(e);
        }
    }
    
    Ok(())
}

async fn run_concurrent_transfers(client: &mut FtpClient, args: &Args, enable_resume: bool, checksum_type: Option<ChecksumType>, priority: TransferPriority) -> Result<()> {
    info!("Starting concurrent transfers...");
    
    // 处理多文件上传
    if let Some(upload_files) = &args.upload_multiple {
        let files: Vec<&str> = upload_files.split(',').map(|s| s.trim()).collect();
        for file in files {
            if let Some(local_path) = &args.local_path {
                let task_id = client.add_concurrent_upload(
                    file.to_string(),
                    local_path.clone(),
                    checksum_type.clone(),
                    enable_resume,
                    priority.clone()
                ).await?;
                info!("Added upload task {}: {} -> {} (priority: {:?})", task_id, local_path, file, priority);
            }
        }
    }
    
    // 处理多文件下载
    if let Some(download_files) = &args.download_multiple {
        let files: Vec<&str> = download_files.split(',').map(|s| s.trim()).collect();
        for file in files {
            if let Some(local_path) = &args.local_path {
                let task_id = client.add_concurrent_download(
                    file.to_string(),
                    local_path.clone(),
                    checksum_type.clone(),
                    enable_resume,
                    priority.clone()
                ).await?;
                info!("Added download task {}: {} -> {} (priority: {:?})", task_id, file, local_path, priority);
            }
        }
    }
    
    // 处理单个文件上传/下载
    if let Some(upload_file) = &args.upload {
        if let Some(local_path) = &args.local_path {
            let task_id = client.add_concurrent_upload(
                upload_file.clone(),
                local_path.clone(),
                checksum_type.clone(),
                enable_resume,
                priority.clone()
            ).await?;
            info!("Added upload task {}: {} -> {} (priority: {:?})", task_id, local_path, upload_file, priority);
        }
    }
    
    if let Some(download_file) = &args.download {
        if let Some(local_path) = &args.local_path {
            let task_id = client.add_concurrent_download(
                download_file.clone(),
                local_path.clone(),
                checksum_type.clone(),
                enable_resume,
                priority.clone()
            ).await?;
            info!("Added download task {}: {} -> {} (priority: {:?})", task_id, download_file, local_path, priority);
        }
    }
    
    // 执行并发传输
    client.execute_concurrent_transfers().await?;
    
    // 显示传输状态
    let status = client.get_transfer_status().await?;
    println!("\n📊 Transfer Status:");
    println!("==================");
    
    for task in status {
        let status_icon = match task.status {
            TransferStatus::Pending => "⏳",
            TransferStatus::Running => "🔄",
            TransferStatus::Completed => "✅",
            TransferStatus::Failed => "❌",
            TransferStatus::Cancelled => "🚫",
        };
        
        println!("{} Task {}: {:?}", status_icon, task.id, task.task);
        println!("   Status: {:?}", task.status);
        println!("   Progress: {:.1}%", task.progress * 100.0);
        println!("   Bytes: {} / {:?}", task.bytes_transferred, task.total_bytes.unwrap_or(0));
        println!("   Speed: {:.2} KB/s", task.speed / 1024.0);
        
        if let Some(error) = &task.error {
            println!("   Error: {}", error);
        }
        
        if let Some(result) = &task.result {
            println!("   Duration: {:.2}s", result.duration.as_secs_f64());
            if result.resumed {
                println!("   Resumed from offset: {} bytes", result.resume_offset);
            }
            if let Some(ref checksum) = result.checksum {
                println!("   Checksum: {} ({:?})", checksum.checksum, checksum.checksum_type);
            }
            if result.integrity_verified {
                println!("   Integrity verification: ✅ PASSED");
            } else {
                println!("   Integrity verification: ❌ FAILED");
            }
        }
        println!();
    }
    
    // 等待所有传输完成
    println!("⏳ Waiting for all transfers to complete...");
    client.wait_for_transfers().await?;
    
    println!("🎉 All concurrent transfers completed!");
    
    Ok(())
}

async fn show_queue_statistics(client: &mut FtpClient) -> Result<()> {
    info!("Showing queue statistics...");
    
    if let Some(manager) = client.get_concurrent_manager() {
        let stats = manager.get_queue_stats().await;
        println!("Total tasks: {}", stats.total_tasks);
        println!("Pending tasks: {}", stats.pending_tasks);
        println!("Running tasks: {}", stats.running_tasks);
        println!("Completed tasks: {}", stats.completed_tasks);
        println!("Failed tasks: {}", stats.failed_tasks);
        println!("Cancelled tasks: {}", stats.cancelled_tasks);
        println!("Queue length: {}", stats.queue_length);
        
        // 显示任务详情
        let all_tasks = manager.get_all_tasks().await;
        if !all_tasks.is_empty() {
            println!("\n📋 Task Details:");
            println!("================");
            
            for task in all_tasks {
                let status_icon = match task.status {
                    TransferStatus::Pending => "⏳",
                    TransferStatus::Running => "🔄",
                    TransferStatus::Completed => "✅",
                    TransferStatus::Failed => "❌",
                    TransferStatus::Cancelled => "🚫",
                };
                
                println!("{} Task {}: {:?}", status_icon, task.id, task.task);
                println!("   Priority: {:?}", task.priority);
                println!("   Status: {:?}", task.status);
                println!("   Progress: {:.1}%", task.progress * 100.0);
                println!("   Created: {:?}", task.created_at);
                
                if let Some(started_at) = task.started_at {
                    println!("   Started: {:?}", started_at);
                }
                
                if let Some(completed_at) = task.completed_at {
                    println!("   Completed: {:?}", completed_at);
                }
                
                if let Some(error) = &task.error {
                    println!("   Error: {}", error);
                }
                
                println!();
            }
        }
    } else {
        println!("No concurrent transfer manager available");
    }
    
    Ok(())
}
